package com.smart5G.service.Impl;

import com.smart5G.dao.*;
import com.smart5G.model.*;
import com.smart5G.service.DataInitService;
import com.smart5G.utils.DataSimulator;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class DataInitServiceImpl implements DataInitService {
    @Autowired
    ServiceMapper serviceMapper;

    @Autowired
    OrderMapper orderMapper;

    @Autowired
    MaintainMapper maintainMapper;

    @Autowired
    NetworkMapper networkMapper;

    @Autowired
    NetworkInfoMapper networkInfoMapper;

    @Override
    public Boolean initService(){
        ServiceExample example = new ServiceExample();
        ServiceExample.Criteria criteria = example.createCriteria();
        criteria.andServiceIdIsNotNull();
        serviceMapper.deleteByExample(example);
        HashMap<String, DataSimulator.Area> hashMap = DataSimulator.readExcel();
        List<DataSimulator.Area> areas = hashMap.values().stream().collect(Collectors.toList());
        for (DataSimulator.Area area :
                areas) {
            com.smart5G.model.Service record = new com.smart5G.model.Service();
            record.setServiceId(area.code+"");
            record.setCity(area.city);
            record.setServiceName(area.name);
            record.setLatitude(area.latitude+"");
            record.setLongitude(area.longitude+"");
            record.setProvince(area.province);
            serviceMapper.insert(record);
        }
        return true;
    }


    public int upperBound(List<DataSimulator.Area> areaList, double value) {
        int low = 0;
        int high = areaList.size();
        while (low < high) {
            final int mid = (low + high) / 2;
            if (value >= areaList.get(mid).Accumulate) {
                low = mid + 1;
            } else {
                high = mid;
            }
        }
        return low;
    }

    @Override
    public Boolean initOrder() {
        int size = 150000;
        double man = 0.58, woman = 0.42;
        double device = 0.24, num = 0.6, bandwidth = 0.16;
        class Age{
            int a;
            double b;

            public Age(int a, double b) {
                this.a = a;
                this.b = b;
            }
        }
        class Brand{
            String name;
            double rank;//品牌占比
            Age age;//年龄分布

            public Brand(String name, double rank, Age age) {
                this.name = name;
                this.rank = rank;
                this.age = age;
            }
        }

        List<Brand> list = new LinkedList<>();
        list.add(new Brand("华为", 0.36,new Age(28, 8)));
        list.add(new Brand("OPPO", 0.12,new Age(27, 13)));
        list.add(new Brand("VIVO", 0.12,new Age(27, 14)));
        list.add(new Brand("小米", 0.23,new Age(32, 12)));
        list.add(new Brand("苹果", 0.07,new Age(30, 6)));
        list.add(new Brand("三星", 0.03,new Age(30, 6)));
        list.add(new Brand("思科", 0.03,new Age(35, 15)));
        list.add(new Brand("其他", 0.04,new Age(29, 3)));
        OrderExample orderExample = new OrderExample();
        OrderExample.Criteria  criteria1 = orderExample.createCriteria();
        criteria1.andOrderIdIsNotNull();
        orderMapper.deleteByExample(orderExample);
        ServiceExample serviceExample = new ServiceExample();
        ServiceExample.Criteria criteria = serviceExample.createCriteria();
        criteria.andServiceIdIsNotNull();
        List<com.smart5G.model.Service> serviceList = serviceMapper.selectByExample(serviceExample);
        serviceList = serviceList.stream().filter(service ->{return service.getProvince().equals("北京市")||service.getProvince().equals("山东省")||service.getProvince().equals("河北省")||service.getProvince().equals("江苏省");}).collect(Collectors.toList());
        List<DataSimulator.Area> areaList = DataSimulator.run(serviceList);
        for (Brand brand : list) {
            int sum = (int)(size*brand.rank);
            int day = sum/270;
            int dayCount = 0;
            Calendar c = Calendar.getInstance();
            c.add(Calendar.DAY_OF_MONTH, -270);
            while (sum-->0) {
                Random random = new Random();
                Order order = new Order();
                order.setOrderId(UUID.randomUUID().toString());
                dayCount++;
                order.setCreateTime(c.getTime());
                if (dayCount==day) {
                    dayCount = 0;
                    c.add(Calendar.DAY_OF_MONTH, 1);
                }
                order.setSex(Math.random()<=man?0:1);
                order.setAge((int)(brand.age.b*random.nextGaussian()+brand.age.a));
                order.setDeviceBrand(brand.name);

                //类型和价格
                double ran = Math.random();
                if (ran <device) {
                    //设备
                    order.setDeviceType(0);
                    order.setPrice(new BigDecimal(3000));
                }else if (ran < device+num) {
                    //号卡
                    order.setDeviceType(1);
                    order.setPrice(new BigDecimal(99));
                }else {
                    //带宽
                    order.setDeviceType(2);
                    order.setPrice(new BigDecimal(69));
                }

                //分配给营业厅
                //serviceList
                int k = upperBound(areaList, Math.random());
                com.smart5G.model.Service service = serviceList.get(k);
                order.setServiceId(service.getServiceId());
                order.setServiceName(service.getServiceName());
                order.setLongitude(service.getLongitude());
                order.setLatitude(service.getLatitude());
                order.setProvince(service.getProvince());
                order.setCity(service.getCity());

                orderMapper.insert(order);
            }
        }
        return true;
    }

    @Override
    public Boolean initFlow() {
        NetworkExample example = new NetworkExample();
        networkMapper.deleteByExample(example);
        NetworkInfoExample exampleinfo = new NetworkInfoExample();
        networkInfoMapper.deleteByExample(exampleinfo);
        //营业厅列表
        ServiceExample serviceExample = new ServiceExample();
        ServiceExample.Criteria criteria = serviceExample.createCriteria();
        criteria.andServiceIdIsNotNull();
        List<com.smart5G.model.Service> serviceList = serviceMapper.selectByExample(serviceExample);
        serviceList = serviceList.stream().filter(service -> Integer.parseInt(service.getServiceId())%100==0||service.getServiceId().startsWith("110")).collect(Collectors.toList());
        serviceList = serviceList.stream().filter(service ->{return service.getProvince().equals("北京市")||service.getProvince().equals("山东省")||service.getProvince().equals("河北省")||service.getProvince().equals("江苏省");}).collect(Collectors.toList());

        double num = 0.8, bandwidth = 0.2;
        class Brand{
            String name;
            double rank;//品牌占比

            public Brand(String name, double rank) {
                this.name = name;
                this.rank = rank;
            }
        }
        List<Brand> list = new LinkedList<>();
        list.add(new Brand("华为", 0.3));
        list.add(new Brand("OPPO", 0.11));
        list.add(new Brand("VIVO", 0.11));
        list.add(new Brand("小米", 0.13));
        list.add(new Brand("苹果", 0.26));
        list.add(new Brand("三星", 0.03));
        list.add(new Brand("思科", 0.03));
        list.add(new Brand("其他", 0.03));

        List<DataSimulator.Area> areaList = DataSimulator.run(serviceList);
        for (Brand brand : list) {
            int sum = 270;
            Calendar c = Calendar.getInstance();
            c.add(Calendar.DAY_OF_MONTH, -270);
            while (sum-->0) {
                for (DataSimulator.Area area : areaList) {
                    Random random = new Random();
                    Network network = new Network();
                    network.setNetworkId(UUID.randomUUID().toString());
                    network.setDayTime(c.getTime());
                    network.setDeviceBrand(brand.name);
                    network.setRealLatitude(area.latitude+"");
                    network.setRealLongitude(area.longitude+"");
                    if (area.city.equals("北京市")){
                        network.setRealCity(area.name);
                    }else {
                        network.setRealCity(area.city);
                    }
                    network.setRealProvince(area.province);
                    //类型和价格
                    double ran = Math.random();
                    if (ran < num) {
                        //号卡
                        network.setDeviceType(1);
                        network.setNetworkSpeed((area.factor+ Math.random()*285+15));
                    }else {
                        //带宽
                        network.setDeviceType(2);
                        network.setNetworkSpeed(area.factor+ Math.random()*30+10);
                    }

                    networkMapper.insert(network);
                }
            }
        }
        return true;
    }

    @Override
    public Boolean initAggregateFlow() {

        return null;
    }

    @Override
    public Boolean initMaintain() {
        //营业厅列表
        ServiceExample serviceExample = new ServiceExample();
        ServiceExample.Criteria criteria = serviceExample.createCriteria();
        criteria.andServiceIdIsNotNull();
        List<com.smart5G.model.Service> serviceList = serviceMapper.selectByExample(serviceExample);
        serviceList = serviceList.stream().filter(service ->{return service.getProvince().equals("北京市")||service.getProvince().equals("山东省")||service.getProvince().equals("河北省")||service.getProvince().equals("江苏省");}).collect(Collectors.toList());
        MaintainExample example = new MaintainExample();
        maintainMapper.deleteByExample(example);
        int size = 5000;
        double man = 0.58, woman = 0.42;
        double device = 0.26, num = 0.36, bandwidth = 0.48;
        class Brand{
            String name;
            double rank;//品牌占比

            public Brand(String name, double rank) {
                this.name = name;
                this.rank = rank;
            }
        }
        List<Brand> list = new LinkedList<>();
        list.add(new Brand("华为", 0.07));
        list.add(new Brand("OPPO", 0.13));
        list.add(new Brand("VIVO", 0.12));
        list.add(new Brand("小米", 0.13));
        list.add(new Brand("苹果", 0.05));
        list.add(new Brand("三星", 0.02));
        list.add(new Brand("思科", 0.15));
        list.add(new Brand("其他", 0.33));

        List<DataSimulator.Area> areaList = DataSimulator.run(serviceList);
        for (Brand brand : list) {
            int sum = (int)(size*brand.rank);
            int day = sum/270;
            int dayCount = 0;
            Calendar c = Calendar.getInstance();
            c.add(Calendar.DAY_OF_MONTH, -270);
            while (sum-->0) {
                Random random = new Random();
                Maintain maintain = new Maintain();
                maintain.setMaintainId(UUID.randomUUID().toString());
                dayCount++;
                maintain.setMaintainDate(c.getTime());
                if (dayCount==day) {
                    dayCount = 0;
                    c.add(Calendar.DAY_OF_MONTH, 1);
                }

                maintain.setDeviceBrand(brand.name);

                //类型和价格
                double ran = Math.random();
                if (ran <device) {
                    //设备
                    maintain.setMaintainType(0);
                }else if (ran < device+num) {
                    //号卡
                    maintain.setMaintainType(1);
                }else {
                    //带宽
                    maintain.setMaintainType(2);
                }

                //分配给营业厅
                //serviceList
                int k = upperBound(areaList, Math.random());
                com.smart5G.model.Service service = serviceList.get(k);
                maintain.setServiceId(service.getServiceId());
                maintain.setServiceName(service.getServiceName());
                maintain.setLongitude(service.getLongitude());
                maintain.setLatitude(service.getLatitude());
                maintain.setProvince(service.getProvince());
                maintain.setCity(service.getCity());

                maintainMapper.insert(maintain);
            }
        }
        return true;
    }

    @Override
    public List<com.smart5G.model.Service> queryService() {
        ServiceExample serviceExample = new ServiceExample();
        ServiceExample.Criteria criteria = serviceExample.createCriteria();
        criteria.andServiceIdIsNotNull();
        List<com.smart5G.model.Service> serviceList = serviceMapper.selectByExample(serviceExample);
        return serviceList;
    }
}
